package org.misty.bloomfilter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class RedisTemplateAdapter implements BloomFilter.IRedisClient<RedisScript<?>> {
    private final static ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<>();
    private final StringRedisTemplate redisTemplate;

    public RedisTemplateAdapter(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public RedisScript<?> scriptLoad(String script, Class<?> resultType) {
        Object rs = cache.get(script);
        if (!(rs instanceof RedisScript)) {
            while (true) {
                Object old = cache.putIfAbsent(script, Boolean.TRUE);
                if (old == Boolean.TRUE) { // 没抢到锁，概率最高
                    Thread.yield();
                } else if (old instanceof RedisScript) {
                    rs = old;
                    break;
                } else if (old == null) { // 抢到锁，概率最低
                    var ns = RedisScript.of(script, resultType);
                    log.debug("load script: {}\n<<<===\n{}\n===>>>", ns.getSha1(), script);
                    cache.put(script, rs = ns);
                    break;
                } else {
                    throw new RuntimeException("不兼容的数据: " + old);
                }
            }
        }
        return (RedisScript<?>) rs;
    }

    @Override
    public Object eval(String script, Class<?> resultType, List<String> keys, String... args) {
        RedisScript<?> rs = scriptLoad(script, resultType);
        return redisTemplate.execute(rs, keys, (Object[]) args);
    }
}
